// tge.rs
// copyright zipxing@hotmail.com 2022~2023

//! cell是tge.rs中的基本绘制数据结构，表示一个"字符"，
//! cell包含symbol,fg,bg几个关键数据，cell构成buffer管理渲染，
//! 一个buffer包含一个长度为width * height的cell vector,
//! 
//! 对cell的应用，参看buffer.rs的注释和代码
//! 参看sdl.rs中的sdlsym实现和SDL_SYM_MAP处理
//! get_sdl_info获取cell的sdl基本信息
//!
//! SDL模式下，为了支持sprite重叠透明绘制，
//! 为Cell添加了sdl_history字段记录符号和颜色列表，
//! 在sprite每次merge或blit到主buffer时，把需要绘
//! 制的符号和颜色push到sdl_history里，渲染时按透
//! 明度依次绘制在render_texture中，然后再把
//! render_texture绘制展示在canva里.
//! 参看本文件的push_sdl_history以及merge和blit方法.
//! 参看terminal.rs在SDL模式下的flush方法.

use crate::render::style::{Color, Modifier, Style};
use crate::render::adapter::sdl::SdlCellInfo;
#[cfg(feature = "sdl")]
use crate::render::adapter::sdl::{sdlsym, sdlinfo};
use serde::{Deserialize, Serialize};

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Cell {
    pub symbol: String,
    pub fg: Color,
    pub bg: Color,
    pub modifier: Modifier,
    pub sdl_history: Vec<SdlCellInfo>,
}

impl Cell {
    pub fn set_symbol(&mut self, symbol: &str) -> &mut Cell {
        self.symbol.clear();
        self.symbol.push_str(symbol);
        self
    }

    /// SDL模式下应用，参考模块的注释
    /// 返回字符偏移量和纹理序号
    /// 对应utf8三字节模式: 11100010 100010xx 10xxxxxx
    /// 从utf8字节序列中取出8位idx，标识纹理中的偏移量
    /// 具体使用参考terminal.rs的flush方法
    /// sym_index, texture_index, fg_color_index
    #[cfg(feature = "sdl")]
    pub fn get_sdl_info(&self) -> SdlCellInfo {
        (sdlinfo(&self.symbol), u8::from(self.bg), u8::from(self.fg))
    }

    pub fn set_char(&mut self, ch: char) -> &mut Cell {
        self.symbol.clear();
        self.symbol.push(ch);
        self
    }

    pub fn set_fg(&mut self, color: Color) -> &mut Cell {
        self.fg = color;
        self
    }

    pub fn set_bg(&mut self, color: Color) -> &mut Cell {
        self.bg = color;
        self
    }

    pub fn set_style(&mut self, style: Style) -> &mut Cell {
        if let Some(c) = style.fg {
            self.fg = c;
        }
        if let Some(c) = style.bg {
            self.bg = c;
        }
        self.modifier.insert(style.add_modifier);
        self.modifier.remove(style.sub_modifier);
        self
    }

    pub fn style(&self) -> Style {
        Style::default()
            .fg(self.fg)
            .bg(self.bg)
            .add_modifier(self.modifier)
    }

    pub fn push_history(&mut self) {
        #[cfg(feature = "sdl")]
        self.sdl_history.push(self.get_sdl_info());
    }

    pub fn reset(&mut self) {
        self.symbol.clear();
        self.symbol.push(' ');
        self.fg = Color::Reset;
        self.bg = Color::Reset;
        self.modifier = Modifier::empty();
        self.sdl_history.clear();
    }

    #[cfg(feature = "sdl")]
    pub fn is_blank(&self) -> bool {
        self.symbol == " " || self.symbol == sdlsym(32)
    }

    #[cfg(not(feature = "sdl"))]
    pub fn is_blank(&self) -> bool {
        self.symbol == " " && self.fg == Color::Reset && self.bg == Color::Reset
    }
}

impl Default for Cell {
    fn default() -> Cell {
        Cell {
            symbol: " ".into(),
            fg: Color::Reset,
            bg: Color::Reset,
            modifier: Modifier::empty(),
            sdl_history: vec![],
        }
    }
}
